import { PrismaClient, Clipboard, RendererConfig, FilowDirItem, Prisma, NotaData } from './client';

// as ISqliteResolveInfo
export interface IResolveInfo<T> {
    data?: T;
    deleteRecord?: T; // 删除的记录
    hasSameRecord?: boolean; // 是否存在相同记录
}

let prisma: PrismaClient;

function load() {
    if (prisma) {
        // ...
    } else {
        prisma = new PrismaClient();
    }
}

/**
 * ******************************************************************************************************************************** Renderer 配置
 */
const rendererConfig = {
    async search(project: string) {
        load();
        const resolveInfo: IResolveInfo<RendererConfig> = {};
        try {
            const result = await prisma.rendererConfig.findFirst({ where: { project } });
            if (result) {
                resolveInfo.data = result;
            }
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.rendererConfig.updateConfig error -> ', e);
            return Promise.reject(e);
        }
    },

    async update(project: string, config: string) {
        load();
        const resolveInfo: IResolveInfo<RendererConfig> = {};
        try {
            resolveInfo.data = await prisma.rendererConfig.upsert({
                create: { project, config },
                update: { project, config },
                where: { project },
            });
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.rendererConfig.update error -> ', e);
            return Promise.reject(e);
        }
    },
};

/**
 * ******************************************************************************************************************************** 剪贴板
 */
const clipboard = {
    /**
     * 添加记录
     *
     * options.deleteSameRecord 是否删除相同记录
     */
    async createOne(data: { content: string }, options?: { deleteSameRecord?: boolean }) {
        load();
        const resolveInfo: IResolveInfo<Clipboard> = {};
        try {
            resolveInfo.data = await prisma.clipboard.create({ data });
            return resolveInfo;
        } catch (e) {
            try {
                if (e instanceof Prisma.PrismaClientKnownRequestError) {
                    switch (e.code) {
                        case 'P2002': {
                            resolveInfo.hasSameRecord = true;

                            // 删除相同记录，插入新记录
                            if (options?.deleteSameRecord) {
                                const deleteSuccess = await prisma.clipboard.delete({ where: { content: data.content } });
                                if (deleteSuccess) {
                                    resolveInfo.deleteRecord = deleteSuccess;
                                    resolveInfo.data = await prisma.clipboard.create({ data });
                                    return resolveInfo;
                                }
                            }

                            return resolveInfo;
                        }
                    }
                }

                // ...
                console.error('sqlite.clipboard.createOne error -> ', e);
                return Promise.reject(e);
            } catch (e) {
                console.error('sqlite.clipboard.createOne error -> ', e);
                return Promise.reject(e);
            }
        }
    },

    /**
     * 删除记录
     */
    async deleteOne(id: number) {
        load();
        const resolveInfo: IResolveInfo<Clipboard> = {};
        try {
            resolveInfo.data = await prisma.clipboard.delete({ where: { id } });
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.clipboard.deleteOne error -> ', e);
            return Promise.reject(e);
        }
    },

    /**
     * 删除所有记录
     */
    async deleteAll() {
        try {
            load();
            await prisma.clipboard.deleteMany();
        } catch (e) {
            console.error('sqlite.clipboard.deleteAll error -> ', e);
            return Promise.reject(e);
        }
    },

    /**
     * 查询所有记录
     *
     * options.reverse 反转列表记录
     */
    async searchAll(options?: { reverse?: boolean }) {
        load();
        const resolveInfo: IResolveInfo<Clipboard[]> = {};
        try {
            resolveInfo.data = await prisma.clipboard.findMany();
            if (options?.reverse) {
                resolveInfo.data = resolveInfo.data.reverse();
            }
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.clipboard.searchAll error -> ', e);
            return Promise.reject(e);
        }
    },
};

/**
 * ******************************************************************************************************************************** Filow 目录项
 */
const filowDirItem = {
    async searchAll() {
        load();
        const resolveInfo: IResolveInfo<FilowDirItem[]> = {};
        try {
            const result = await prisma.filowDirItem.findMany();
            if (result) {
                resolveInfo.data = result;
            }
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.filowDirItem.searchAll error -> ', e);
            return Promise.reject(e);
        }
    },

    async update(id: number, name: string, path: string) {
        load();
        const resolveInfo: IResolveInfo<FilowDirItem> = {};
        try {
            resolveInfo.data = await prisma.filowDirItem.upsert({
                create: { name, path },
                update: { name, path },
                where: { id },
            });
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.filowDirItem.update error -> ', e);
            return Promise.reject(e);
        }
    },

    async delete(id: number) {
        load();
        const resolveInfo: IResolveInfo<FilowDirItem> = {};
        try {
            const deleteSuccess = await prisma.filowDirItem.delete({ where: { id } });
            if (deleteSuccess) {
                resolveInfo.deleteRecord = deleteSuccess;
            }
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.filowDirItem.delete error -> ', e);
            return Promise.reject(e);
        }
    },
};

/**
 * ******************************************************************************************************************************** Nota
 */
const nota = {
    async searchDataList() {
        load();
        const resolveInfo: IResolveInfo<Array<NotaData>> = {};
        try {
            const result = await prisma.notaData.findMany();
            if (result) {
                resolveInfo.data = result;
            }
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.nota.searchDataList error -> ', e);
            return Promise.reject(e);
        }
    },

    async updateDatas(datas: Array<NotaData>) {
        load();
        const resolveInfo: IResolveInfo<null> = {};
        try {
            for (const data of datas) {
                await prisma.notaData.upsert({
                    where: { id: data.id },
                    update: data,
                    create: data,
                });
            }
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.nota.updateDatas error -> ', e);
            return Promise.reject(e);
        }
    },

    async removeData(id: string) {
        load();
        const resolveInfo: IResolveInfo<NotaData> = {};
        try {
            const result = await prisma.notaData.delete({ where: { id } });
            resolveInfo.data = result;
            return resolveInfo;
        } catch (e) {
            console.error('sqlite.nota.removeData error -> ', e);
            return Promise.reject(e);
        }
    },
};

/**
 * ******************************************************************************************************************************** export module
 */
export * from './client';

// as sqlite
export default {
    nota,
    clipboard,
    filowDirItem,
    rendererConfig,
};
